package infomap

import groovyx.net.http.RESTClient
import infomap.smsSender.SMSSender
import twitter4j.Twitter
import twitter4j.TwitterFactory
import twitter4j.auth.RequestToken
import twitter4j.auth.AccessToken
import twitter4j.TwitterException
import twitter4j.Status
import org.scribe.model.Response
import org.scribe.model.Verb
import org.scribe.model.OAuthRequest
import org.scribe.model.Token
import org.scribe.model.Verifier
import org.scribe.builder.api.TwitterApi
import org.scribe.builder.ServiceBuilder
import org.scribe.oauth.OAuthService
import grails.converters.deep.JSON
import java.lang.Math

/**
 * User: mwaisgold
 * Date: 08/11/11
 * Time: 00:44
 */
class TwitterRefreshJob {

    def group = "Mygroup"
    def concurrent = false
    def twitterClient = new RESTClient("https://api.twitter.com/1/")
    def googleClient = new RESTClient("http://maps.google.com/maps/api/geocode/")
    SMSSender smsSender
    def mailService
    private static final String PROTECTED_RESOURCE_URL = "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=tdpinfomap&count=5";

    static Long LAST_STATUS_ID = null

    static triggers = {
        simple name: "Twitter job", repeatCount: -1, repeatInterval: 60000, startDelay: 2000
    }

    def execute(){

        //def statuses = twitter.getUserTimeline("tdpinfomap", 10, LAST_STATUS_ID)
        def params = [screen_name:"tdpinfomap", count:2]
        if (LAST_STATUS_ID){
            params.since_id = LAST_STATUS_ID
        }


//        Twitter twitter = new TwitterFactory().getInstance();
//        twitter.setOAuthConsumer("r9Ll1nB2AgIsCbkHBRAINA","Zb88qoRdvO2Zb7OZln0dvo1SknsdU1p4CcfSX8Spk");
//        println twitter.getOAuthAccessToken("tdpinfomap","tdpinfomap");

        OAuthService service = new ServiceBuilder()
                            .provider(TwitterApi.class)
                            .apiKey("6icbcAXyZx67r8uTAUM5Qw")
                            .apiSecret("SCCAdUUc6LXxiazxH3N0QfpNUvlUy84mZ2XZKiv39s")
                            .build();
//    Scanner ain = new Scanner(System.in);
//
//    System.out.println("=== Twitter's OAuth Workflow ===");
//    System.out.println();
//
//    // Obtain the Request Token
//    System.out.println("Fetching the Request Token...");
//    Token requestToken = service.getRequestToken();
//    System.out.println("Got the Request Token!");
//    System.out.println();
//
//    System.out.println("Now go and authorize Scribe here:");
//    System.out.println(service.getAuthorizationUrl(requestToken));
//    System.out.println("And paste the verifier here");
//    System.out.print(">>");
//    Verifier verifier = new Verifier("9852898");
//    System.out.println();
//
//
//
//    // Trade the Request Token and Verfier for the Access Token
//    System.out.println("Trading the Request Token for an Access Token...");
//    Token accessToken = service.getAccessToken(requestToken, verifier);
//    System.out.println("Got the Access Token!");
//    System.out.println("(if your curious it looks like this: " + accessToken + " )");
//    System.out.println();

        def token = new Token("145302828-ShOoocWp4sY6jAX87qwrCoC4KU5xSlrTVEX1rap7", "fAGuPr0oPhktaLmfDmX13ArlCkvwONlQANbrpMy7LjE" )

        // Now let's go and ask for a protected resource!
        def url = PROTECTED_RESOURCE_URL
        if (LAST_STATUS_ID){
            url = "$url&since_id=$LAST_STATUS_ID"
        }

        OAuthRequest request = new OAuthRequest(Verb.GET, url);
        service.signRequest(token, request);
        Response response = request.send();

        //System.out.println(response.getBody());
        //def statuses = twitterClient.get(path: "statuses/user_timeline.json", query: params).data
        def statuses = JSON.parse(response.getBody())
        println statuses.text

        statuses.each {
            String text = it.text.toLowerCase()
            if (text.contains("accidente en")){
                def address = text.replaceAll("accidente en", "")
                def position = googleClient.get(path:"json", query: [address: "$address, Capital Federal", region:"ar",sensor: "false"]).data
                def barrio = position.results[0].address_components.find {
                    "neighborhood" in it.types
                }
                def nombreBarrio = barrio.long_name

                def zona = Zona.findByNombre(nombreBarrio)

                def eventoVial = new EventoVial(descripcion: text, fecha: new Date(), barrio: nombreBarrio)
                def latlong = position.results[0].geometry.location
                def ubicacionEvento = new Ubicacion(latitud: latlong.lat, longitud: latlong.lng)
                eventoVial.ubicacion = ubicacionEvento
                eventoVial.ubicacion.save(flush:true)
                eventoVial.save(flush: true)

                zona.usuarios.each { Usuario usuario ->
                    if (usuario.recibeSms()){
                        smsSender.sendMessage(usuario, text)
                    }

                    if (usuario.recibeMail()){
                        //TODO: enviar un mail (se me ocurrio poner un mapa aca, implementalo pajero)
                        println "Sending mail to $usuario.mail"
                        mailService.sendMail {
                          to usuario.mail
                          subject "Nuevo evento en el tránsito en $nombreBarrio"
                          body( view:"/mail/sendEventoMail",
                              model:[usuario: usuario, zona: zona, textoMensaje: text, address: address])
                        }
                    }
                }

                Recorrido.list().each {
                    def recorrido = it
                    def notificar = false
                    def path = "";
                    Ubicacion origen, destino

                    List puntosRecorrido = recorrido.puntosIntermedios.toList().sort{ p1, p2 -> p1.id <=> p2.id }
                    def puntosIterator =  puntosRecorrido.iterator()
                    origen = puntosIterator.next()
                    while (puntosIterator.hasNext()){
                        destino = puntosIterator.next()
                        if (esCercano(origen, destino, ubicacionEvento)){
                            notificar = true
                            path+= "|" + origen.latitud + "," + origen.longitud
                            path+= "|" + destino.latitud + "," + destino.longitud
                        }
                        origen = destino
                    }

                    if (notificar) {
                        Usuario usuario = recorrido.usuario
                        if (usuario.recibeSms()){
                            smsSender.sendMessage(usuario, text)
                        }

                        if (usuario.recibeMail()){
                            println "Sending mail to $usuario.mail"
                            mailService.sendMail {
                              to usuario.mail
                              subject "Nuevo evento en el tránsito en $nombreBarrio"
                              body( view:"/mail/sendRecorridoMail",
                                  model:[usuario: usuario, textoMensaje: text, address: address, recorrido: recorrido, path: path])
                            }
                        }
                    }

                }
                //println barrio
            }else if (text.contains("paro en")){
                def servicioNombre = text.replaceAll("paro en", "")
                def servicio = Servicio.findByDescripcion(servicioNombre)

                servicio.estado = Servicio.ESTADO_PARO
                def evento = new EventoNoVial(descripcion: text)
                evento.addToServicio(servicio)

                evento.save()
                servicio.save()

            } else if (text.contains("demoras en")){
                def servicioNombre = text.replaceAll("demoras en", "")
                def servicio = Servicio.findByDescripcion(servicioNombre)

                servicio.estado = Servicio.ESTADO_DEMORADO
                def evento = new EventoNoVial(descripcion: text)
                evento.addToServicio(servicio)

                evento.save()
                servicio.save()
            }
        }


        LAST_STATUS_ID = statuses.id.max() ?: LAST_STATUS_ID



        //def statuses = twitterService.getFriendsTimeline()

        //LAST_JOB_RUN = new Date()
    }

    def esCercano (Ubicacion origen, Ubicacion destino, Ubicacion evento){
        def distanciaRecorrido = calcularDistancia(origen, destino)
        def distanciaEvento = calcularDistancia(origen, evento) + calcularDistancia(evento, destino)

        return (distanciaRecorrido > distanciaEvento - 500)
    }

    static final double DEG_TO_RAD = 0.017453292519943295769236907684886;
    static final double EARTH_RADIUS_IN_METERS = 6372797.560856;

    def calcularDistancia(Ubicacion origen, Ubicacion destino){
        double latitudeArc  = (origen.latitud - destino.latitud) * DEG_TO_RAD;
        double longitudeArc = (origen.longitud - destino.longitud) * DEG_TO_RAD;
        double latitudeH = Math.sin(latitudeArc * 0.5);
        latitudeH *= latitudeH;
        double longitudeH = Math.sin(longitudeArc * 0.5);
        longitudeH *= longitudeH;
        double tmp = Math.cos(origen.latitud*DEG_TO_RAD) * Math.cos(destino.latitud*DEG_TO_RAD);

        return EARTH_RADIUS_IN_METERS * 2.0 * Math.asin(Math.sqrt(latitudeH + tmp*longitudeH));
    }
}
